cover picture sponsor: gleammming.art
在先前學習語法與實作當中,我們所撰寫的 JavaScript 程式碼都是我們直接撰寫好邏輯並且讓它執行,如此一來使用者在瀏覽網頁時都只能被動的接受我們所撰寫好的程式。
而作為事件驅動(event-driven)的程式語言,JavaScript 一開始被發明的原因就是要解決 網頁中即時互動 的問題,所以自然而然也有發明一套機制來負責處理使用者在瀏覽網頁時的一些互動,好讓我們的程式碼不在只是死板板的運算,還多了一個與人互動的機會,而我們稱這些可以讓人與瀏覽器互動的事件為 瀏覽器事件(browser event)。
要在網頁上的特定時機執行程式碼前,我們最主要得先註冊一個事件,使得瀏覽器知道我們在什麼時機下要執行這些程式碼。
而註冊事件的方法總共有三種:
而最早網頁開發時的註冊方式是採用 傳統註冊模型(traditional registration model):
<button id="handleTarget" type="button">Click Me!</button>
handleTarget.onclick = function(){
console.log('Hello, Event!')
}
採用這種方法的時候,若是重複註冊時會蓋過前一個所註冊的事件:
<button id="handleTarget" type="button">Click Me!</button>
handleTarget.onclick = function(){
console.log('Hello, Event!') // 這個最後被蓋過
}
handleTarget.onclick = function(){
console.log('Another Event!')
}
即便使用一個函式來負責處理也是很難管理事件。
而另一個類似的註冊方式則是 行內註冊模型(inline registration model),我們會直接在 HTML 中來撰寫註冊的事件以及需要驅動的函式:
<button type="button" onclick="handleButtonClick()">Click Me!</button>
function handleButtonClick(){
console.log('Hello, Event!')
}
使用行內註冊方法時背後其實也同等於建立一個類似於傳統註冊事件的程式。
在上面我們總共提到傳統註冊模型或是使用行內註冊模型兩種註冊方法,然而不論是哪種註冊方式,其實對於後續的維護上都會造成困擾。
因此在 DOM Level 2 API 規範經由 W3C 委員會定案後,終於出現了一個較好的紓困方式,我們稱其為標準事件模型(或稱 DOM LeveL 2 事件模型)。
使用方法最主要是透過 addEventListener
來進行註冊:
<button id="handleTarget" type="button">Click Me!</button>
handleTarget.addEventListener('click', function(){
console.log('Hello, Event!')
})
這種註冊方式主要是基於註冊事件觸發後執行第二個參數中的回呼函式(callback function),因此我們也可以將該函式獨立出來,如此一來我們就可以有效管理事件:
// 定義函式
var handleClick = function (){
console.log('Hello, Event!')
}
// 集中管理註冊事件
handleTarget.addEventListener('click', handleClick)
handleAnotherTarget.addEventListener('click', handleClick)
handleOtherTarget.addEventListener('click', handleClick)
而為了避免重複註冊了同個事件,也可以透過 removeListener
來進行取消註冊:
// 定義函式
var handleClick = function (){
console.log('Hello, Event!')
}
var initPage = function(){
handleTarget.addEventListener('click', handleClick)
}
var leavePage = function(){
handleTarget.removeEventListener('click', handleClick)
}
initPage() // 初始化頁面時註冊
leavePage() // 離開頁面時取消註冊
現在我們已經知道事件註冊的三種方法了,然而註冊事件時最主要的是我們得要定義是要基於哪個事件而被觸發,而一般較為常見的事件有:
更多詳細資訊可以參考 W3 的 規章
而使用的方法也很簡單,以標準事件模型註冊事件舉例來說,我們只要在 addEventListener
的第一個引數中傳入事件類型即可偵測相關事件:
targetElement.addEventListener('click', handleClick) // 偵測點擊
我們也可以透過回呼函式的第一個參數取得 Event 物件 來取得更多的資訊:
targetElement.addEventListener('click', function(event){
event.currenTarget // 當下的事件目標
event.target // 註冊事件的原始目標
// 族繁不及備載,event 裡面還有更多的資訊
})
接著,眼尖的你可能會發現在 Event 物件資訊中有兩個看起來很相似的內容,一個是 currentTarget
,另一個是 target
,而他們的關係差別在哪?這個問題待我們明天講完 事件捕獲 與 事件冒泡 機制後相信你就能夠瞭解了!